;--------------------------------------------------------------------------------------------------
;Micro Operation System Project Copyright 2012
;Author : Ilya Churaev
;Started : 20 Apr 2012	Updated : 4 May 2012
;File Name : interrupt.asm  Purpose : Contains interrupt service routine wrappers.
;--------------------------------------------------------------------------------------------------

[GLOBAL gdt_flush]			; Позволяет коду на C обращаться gdt_flush().

gdt_flush:
    mov eax, [esp+4]		; Берет указатель на таблицу GDT, переданную в качестве параметра.
    lgdt [eax]				; Загружает новый указатель GDT

    mov ax, 0x10			; 0x10 является смещением, находящимся в таблице GDT и указываемым на наш сегмент данных
    mov ds, ax				; Загрузка переключателей всех сегментов данных
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    jmp 0x08:.flush			; 0x08 является смещением на наш сегмент кода: Длинный переход!
.flush:
    ret

[GLOBAL idt_flush]			; Позволяет коду на C обращаться idt_flush().

idt_flush:
    mov eax, [esp+4]		; Берет указатель на IDT, передаваемый в качестве параметра.
    lidt [eax]				; Загружает указатель IDT.
    ret

[GLOBAL tss_flush]			; Позволяет коду на C обращаться tss_flush().
tss_flush:
	mov ax, 0x2B			; Load the index of our TSS structure - The index is
							; 0x28, as it is the 5th selector and each is 8 bytes
							; long, but we set the bottom two bits (making 0x2B)
							; so that it has an RPL of 3, not zero.
	ltr ax					; Load 0x2B into the task state register.
	ret
    
    
; This macro creates a stub for an ISR which does NOT pass it's own
; error code (adds a dummy errcode byte).
%macro ISR_NOERRCODE 1
[GLOBAL isr%1]				; %1 доступ к первому параметру.
isr%1:
	cli						; Сброс прерываний
	push byte 0				; Помещаем в стек фиктивный код ошибки (в случае, если ISR0 не помещает в стек свой собственный код ошибки)
	push  %1				; Помещаем в стек номер прерывания (0)
	jmp isr_common_stub		; Переходим к общей части обработчика.
%endmacro

; This macro creates a stub for an ISR which passes it's own
; error code.
%macro ISR_ERRCODE 1
[GLOBAL isr%1]
isr%1:
	cli						; Сброс прерываний
	push %1					; Помещаем в стек номер прерывания
	jmp isr_common_stub
%endmacro

; Этот макрос создает кусок кода для IRQ - первым параметром 
; является номер IRQ, вторым - номер ISR, на который осуществляется переназначение.
%macro IRQ 2
[GLOBAL irq%1]
irq%1:
	cli
	push byte 0
	push byte %2
	jmp irq_common_stub
%endmacro
        
ISR_NOERRCODE 0
ISR_NOERRCODE 1
ISR_NOERRCODE 2
ISR_NOERRCODE 3
ISR_NOERRCODE 4
ISR_NOERRCODE 5
ISR_NOERRCODE 6
ISR_NOERRCODE 7
ISR_ERRCODE   8
ISR_NOERRCODE 9
ISR_ERRCODE   10
ISR_ERRCODE   11
ISR_ERRCODE   12
ISR_ERRCODE   13
ISR_ERRCODE   14
ISR_NOERRCODE 15
ISR_NOERRCODE 16
ISR_NOERRCODE 17
ISR_NOERRCODE 18
ISR_NOERRCODE 19
ISR_NOERRCODE 20
ISR_NOERRCODE 21
ISR_NOERRCODE 22
ISR_NOERRCODE 23
ISR_NOERRCODE 24
ISR_NOERRCODE 25
ISR_NOERRCODE 26
ISR_NOERRCODE 27
ISR_NOERRCODE 28
ISR_NOERRCODE 29
ISR_NOERRCODE 30
ISR_NOERRCODE 31
IRQ   0,    32
IRQ   1,    33
IRQ   2,    34
IRQ   3,    35
IRQ   4,    36
IRQ   5,    37
IRQ   6,    38
IRQ   7,    39
IRQ   8,    40
IRQ   9,    41
IRQ  10,    42
IRQ  11,    43
IRQ  12,    44
IRQ  13,    45
IRQ  14,    46
IRQ  15,    47

;Syscalls
ISR_NOERRCODE 128
ISR_NOERRCODE 105 ;0x69
ISR_NOERRCODE 85  ;0x55

; В файле isr.c
[EXTERN isr_handler]

; Это наша общая часть ISR. Она сохраняет состояние процессора, настраивает
; сегменты на использование в режиме ядра, вызывает обработчик отказов, написанный на C
; и, наконец, восстанавливает состояние стека.
isr_common_stub:
	pusha					; Помещает в стек содержимое регистров edi,esi,ebp,esp,ebx,edx,ecx,eax

	mov ax, ds				; Младшие 16 битов регистра eax = ds.
	push eax				; Сохранение дескриптора сегмента данных

    mov ax, 0x10			; Загрузка сегмента данных ядра
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax

	call isr_handler

	pop ebx					; Перезагрузка оригинального дескриптора сегмента данных
	mov ds, bx
	mov es, bx
	mov fs, bx
	mov gs, bx

	popa					; Выталкиваем из стека значения edi,esi,ebp...
	add esp, 8				; Очищаем из стека код ошибки, помещаем в стек номер ISR
	sti
	iret					; Выталкиваем из стека следующие пять значений: CS, EIP, EFLAGS, SS и ESP 

; В isr.c
extern irq_handler

; Это наш общий фрагмент для обработки IRQ. Он сохраняет состояние процессора, настраивает
; сегменты режима ядра, вызывает обработчик прерываний уровня языка C и, в конце концов,
; восстанавливает состояние стека.
irq_common_stub:
	pusha					; Помещает в стек edi,esi,ebp,esp,ebx,edx,ecx,eax

	mov ax, ds				; Младшие 16 битов регистра eax = ds.
	push eax				; сохраняет дескриптор сегмента данных

	mov ax, 0x10			; Загрузка дескриптора сегмента данных ядра
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax

	call irq_handler

	pop ebx					; Перезагрузка исходного дескриптора сегмента данных
	mov ds, bx
	mov es, bx
	mov fs, bx
	mov gs, bx

	popa					; Выталкивает из стека значения edi,esi,ebp...
	add esp, 8				; Очищает код ошибки, помещенный в стек, и помещает в стек номер ISR
    sti
	iret					; выталкивает из стека следующие пять значений: CS, EIP, EFLAGS, SS и ESP
